package com.ev.apis.controller.mes;

import com.ev.apis.model.DsResultResponse;
import com.ev.custom.domain.ContentAssocDO;
import com.ev.custom.service.ContentAssocService;
import com.ev.framework.annotation.EvApiByToken;
import com.ev.framework.config.Constant;
import com.ev.framework.config.ConstantForDevice;
import com.ev.framework.config.ConstantForMES;
import com.ev.framework.il8n.MessageSourceHandler;
import com.ev.framework.utils.R;
import com.ev.framework.utils.ShiroUtils;
import com.ev.mes.domain.CraftDO;
import com.ev.mes.domain.ProcessDO;
import com.ev.mes.domain.WorkingProcedureDetailDO;
import com.ev.mes.service.*;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * Created by Kuzi on 2019-11-21.
 */
@Api(value="/", tags = "工序配置 + + 工艺路线")
@RestController
public class MesProcessAndCraftApiController {

    @Autowired
    private ProcessService processService;
    @Autowired
    private ProcessAutoCollectService processAutoCollectService;
    @Autowired
    private CraftService craftService;
    @Autowired
    private ContentAssocService contentAssocService;
    @Autowired
    private ProcessCheckService processCheckService;
    @Autowired
    private MessageSourceHandler messageSourceHandler;
    @Autowired
    private WorkingProcedurePlanService workingProcedurePlanService;
    @Autowired
    private WorkingProcedureDetailService workingProcedureDetailService;

    @EvApiByToken(value = "/apis/mes/process/addAndChange", method = RequestMethod.POST, apiTitle = "添加/修改 工序配置")
    @ApiOperation("添加/修改 工序配置")
    @Transactional(rollbackFor = Exception.class)
    public R addAndChangeProcess(ProcessDO processDO,
                                 @ApiParam(value = "检验项目明细:[{\"proId\":3,\"whetherCheck\":1(1是 0否),\"remark\":\"备注\",\"uom\":10001,\"min\":1,\"max\":99,\"pointId\":99}]", required = true)  @RequestParam(value = "processCheck", defaultValue = "", required = false) String processCheck,
                                 @ApiParam(value = "测点数组")  @RequestParam(value = "pointList", defaultValue = "", required = false) Long[] pointList,
                                 @ApiParam(value = "上传附件") @RequestParam(value = "uploadAttachment",defaultValue = "",required = false) String  uploadAttachment) {
        //将审核状态变为待审核状态
        if(processDO.getAuditSign()==null){
            processDO.setAuditSign(Constant.WAIT_AUDIT);
        }
        return processService.saveAndChange(processDO, processCheck, "",uploadAttachment,pointList);
    }

    @EvApiByToken(value = "/apis/mes/process/audit", method = RequestMethod.POST, apiTitle = "审核 工序配置")
    @ApiOperation("审核 工序配置")
    @Transactional(rollbackFor = Exception.class)
    public R auditProcess(@ApiParam(value = "工序配置id", required = true)  @RequestParam(value = "id", defaultValue = "", required = false) Long id) {

        ProcessDO processDO = processService.get(id);
        if(Objects.nonNull(processDO)){
            if(Objects.equals(Constant.WAIT_AUDIT,processDO.getAuditSign())){
                ProcessDO processDo1=new ProcessDO();
                processDo1.setAuditSign(Constant.OK_AUDITED);
                processDo1.setAuditId(ShiroUtils.getUserId());
                processDo1.setId(id);
                 processService.update(processDo1);
                return R.ok();
            }else{
                return R.error(messageSourceHandler.getMessage("common.massge.okAudit",null));
            }
        }else{
            return R.error(messageSourceHandler.getMessage("common.massge.haveNoThing",null));
        }
    }

    @EvApiByToken(value = "/apis/mes/process/batchAudit", method = RequestMethod.POST, apiTitle = "批量审核 工序配置")
    @ApiOperation("批量审核 工序配置")
    @Transactional(rollbackFor = Exception.class)
    public R batchAuditProcess(@ApiParam(value = "工序配置Id", required = true) @RequestParam(value = "ids") Long[] ids) {
        if (ids.length > 0) {
            List<ProcessDO> processDOs = processService.getByIds(ids);
            Long userId = ShiroUtils.getUserId();
            for (ProcessDO processDO : processDOs) {
                if (Objects.nonNull(processDO)) {
                    if (Objects.equals(Constant.WAIT_AUDIT, processDO.getAuditSign())) {
                        processDO.setAuditSign(Constant.OK_AUDITED);
                        processDO.setAuditId(userId);
                    } else {
                        return R.error(messageSourceHandler.getMessage("common.massge.okAudit", null));
                    }
                } else {
                    return R.error(messageSourceHandler.getMessage("common.massge.haveNoThing", null));
                }
            }
            for (ProcessDO processDO : processDOs) {
                processService.update(processDO);
            }
            return R.ok();
        }
        return R.error();
    }


    @EvApiByToken(value = "/apis/mes/process/backToAudit", method = RequestMethod.POST, apiTitle = "反审核 工序配置")
    @ApiOperation("反审核 工序配置")
    @Transactional(rollbackFor = Exception.class)
    public R backToAuditProcess(@ApiParam(value = "工序配置id", required = true)  @RequestParam(value = "id", defaultValue = "", required = false) Long id) {

        ProcessDO processDO = processService.get(id);
        if(Objects.nonNull(processDO)){
            if(Objects.equals(Constant.OK_AUDITED,processDO.getAuditSign())){
                ProcessDO processDO1=new ProcessDO();
                processDO1.setAuditSign(Constant.WAIT_AUDIT);
                processDO1.setAuditId(0L);
                processDO1.setId(id);
                processService.update(processDO1);
                return R.ok();
            }else{
                return R.error(messageSourceHandler.getMessage("common.massge.okWaitAudit",null));
            }
        }else{
            return R.error(messageSourceHandler.getMessage("common.massge.haveNoThing",null));
        }
    }




    @EvApiByToken(value = "/apis/mes/process/processOfList", method = RequestMethod.POST, apiTitle = "工序配置列表")
    @ApiOperation("获取工序配置列表")
    @Transactional(rollbackFor = Exception.class)
    public R checkOfList(@ApiParam(value = "当前第几页", required = true) @RequestParam(value = "pageno", defaultValue = "1") int pageno,
                         @ApiParam(value = "一页多少条", required = true) @RequestParam(value = "pagesize", defaultValue = "20") int pagesize,
                         @ApiParam(value = "状态") @RequestParam(value = "useStatus", required = false) Integer useStatus,
                         @ApiParam(value = "审核状态") @RequestParam(value = "auditSign", defaultValue = "", required = false) Integer auditSign,
                         @ApiParam(value = "工序计划id") @RequestParam(value = "planId", defaultValue = "", required = false) Long planId,
                         @ApiParam(value = "工序名称") @RequestParam(value = "name", defaultValue = "", required = false) String name) {

        Map<String, Object> params = Maps.newHashMapWithExpectedSize(5);
        params.put("name", name);
        params.put("offset", (pageno - 1) * pagesize);
        params.put("limit", pagesize);
//        params.put("useStatus", useStatus);
        params.put("auditSign", auditSign);

        //返工返修
        if(Objects.nonNull(planId)){
            Map<String,Object>  map= new HashMap<>();
            map.put("planId",planId);
            List<WorkingProcedureDetailDO> planDetails = workingProcedureDetailService.list(map);
            List<Long>  ids=planDetails.stream().map(WorkingProcedureDetailDO::getProcessId).distinct().collect(Collectors.toList());
            params.put("ids", ids);
        }

        List<Map<String, Object>> list = processService.listForMap(params);
        int count = processService.countListForMap(params);
        Map<String, Object> results = Maps.newHashMapWithExpectedSize(1);
        if (!list.isEmpty()) {

            for (Map<String, Object> listOfOne : list) {
                Map<String, Object> map = new HashMap<>();
                map.put("foreignId", listOfOne.get("id"));
                map.put("type", ConstantForMES.PROCESS_GXPZ);
                List<Map<String, Object>> detailOfProcess = processCheckService.getDetailByProcessId(map);
                listOfOne.put("proDetail", detailOfProcess);
            }

            // 获取附件
            List<Object> detailIds = list.stream()
                    .map(e -> e.get("id"))
                    .collect(Collectors.toList());
            Map<String, Object> fileParam = Maps.newHashMapWithExpectedSize(2);
            fileParam.put("assocIds", detailIds);
            fileParam.put("assocType", ConstantForDevice.PROCESS_FILE);
            List<ContentAssocDO> sopFileList = contentAssocService.list(fileParam);
            if (sopFileList.size() > 0) {
                Map<Long, List<ContentAssocDO>> collect = sopFileList
                        .stream()
                        .collect(Collectors.groupingBy(ContentAssocDO::getAssocId));
                for (Map<String, Object> map : list) {
                    long id = Long.parseLong(map.get("id").toString());
                    if(collect.containsKey(id)){
                        map.put("uploadAttachment", collect.get(id));
                    }
                }
            }

            // 获取测点
            Map<String, Object> param = Maps.newHashMap();
            param.put("type", ConstantForMES.PROCESS_GXPZ);
            param.put("processIds", detailIds);
            List<Map<String, Object>> processAutoCollectDetail = processAutoCollectService.getDetailByProcessId(param);
            if (processAutoCollectDetail.size() > 0) {
                Map<String, List<Map<String, Object>>> collect = processAutoCollectDetail
                        .stream()
                        .collect(Collectors.groupingBy(e -> e.get("processId").toString()));
                for (Map<String, Object> map : list) {
                    String id = map.get("id").toString();
                    if (collect.containsKey(id)) {
                        List<Map<String, Object>> maps = collect.get(id);
                        map.put("processAutoCollectDetail", maps);
                        map.put("pointList", maps.stream().map(e->e.get("pointId")).collect(Collectors.toList()));
                    }
                }
            }

            DsResultResponse dsRet = new DsResultResponse();
            dsRet.setDatas(list);
            dsRet.setPageno(pageno);
            dsRet.setPagesize(pagesize);
            dsRet.setTotalRows(count);
            dsRet.setTotalPages((count + pagesize - 1) / pagesize);
            results.put("data", dsRet);
        }

        return R.ok(results);
    }


    @EvApiByToken(value = "/apis/mes/process/detail", method = RequestMethod.POST, apiTitle = "工序配置详情")
    @ApiOperation("工序配置详情")
    public R detail(@ApiParam(value = "工序配置Id", required = true) @RequestParam(value = "processId", defaultValue = "") Long processId) {

        return processService.getProcessDetail(processId);
    }


    @EvApiByToken(value = "/apis/mes/process/batchDelete", method = RequestMethod.POST, apiTitle = "删除工序配置")
    @ApiOperation("删除工序配置")
    @Transactional(rollbackFor = Exception.class)
    public R batchDelete(@ApiParam(value = "工序配置Id", required = true) @RequestParam(value = "ids") Long[] ids) {
        //若被工艺引用则不能被删除++审核不能删除
        //逻辑删除
        return processService.deteBatchProcess(ids);
    }



/**
*===========================================工艺路线=============================================================================
 */


    @EvApiByToken(value = "/apis/mes/craft/addAndChange", method = RequestMethod.POST, apiTitle = "添加/修改 工艺路线")
    @ApiOperation("添加/修改 工艺路线")
    @Transactional(rollbackFor = Exception.class)
    public R addAndChangeCraft(CraftDO craftDO,
                               @ApiParam(value = "[\n" +
                                       "{\n" +
                                       "\"id\":\"工艺明细行主键(修改时传且必传)\"," +
                                       "\"uploadAttachment\":\"uploadAttachment\"\r\n" +
                                       "\"processId\":2," +
                                       "\"serialNumber\":序号," +
                                       "\"demand\":\"工艺要求\",\"deptId\":\"生产部门\",\"operator\":\"操作工\",\"autoDispatch\":\"是否自动派工\",\n" +
                                       "\"standard\":\"基准良率\",\"type\":\"工序类型\",\"whetherExamine\":\"是否检验\",\"whetherOutsource\":\"是否委外\",\"whetherCollect\":\"是否联网采集\",\n" +
                                       "\"deviceId\":\"使用设备id\",\"totalHour\":\"工作时长\",\"manHour\":\"单件工时\",\"labourPrice\":\"单件工价\",\n" +
                                       "\"pointList\":[1,2,3]," +
                                       "\"pro\":[\n" +
                                       "{\n" +
                                       "\"id\":\"检验项目表主键(修改时传且必传)\",\n" +
                                       "\"foreignId\":\"工艺明细行主键(修改时传且必传)\",\n" +
                                       "\"proId\":\"检验项目主键\",\n" +
                                       "\"remark\":\"备注\",\n" +
                                       "\"whetherCheck\":\"是否必检1是0否\"\n,\"uom\":10001,\"min\":1,\"max\":99,\"pointId\":99" +
                                       "},\n" +
                                       "{\n" +
                                       "\"id\":\"检验项目表主键(修改时传且必传)\",\n" +
                                       "\"foreignId\":\"工艺明细行主键(修改时传且必传)\",\n" +
                                       "\"proId\":\"检验项目主键\",\n" +
                                       "\"remark\":\"备注\",\n" +
                                       "\"whetherCheck\":\"是否必检1是0否\"\n,\"uom\":10001,\"min\":1,\"max\":99,\"pointId\":99" +
                                       "}\n" +
                                       "]\n" +
                                       "}\n" +
                                       "]", required = true)  @RequestParam(value = "processAndProject", defaultValue = "", required = false) String processAndProject,
                               @ApiParam(value = "删除的工艺子表id") @RequestParam(value = "deletCraftItemIds",required = false) Long[] deletCraftItemIds,
                               @ApiParam(value = "删除的检查项目表id") @RequestParam(value = "deletProcessCheckIds",required = false) Long[] deletProcessCheckIds) {

        return craftService.saveAndChangeCraft(craftDO, processAndProject,deletCraftItemIds,deletProcessCheckIds);
    }

    @EvApiByToken(value = "/apis/mes/craft/auditCraft", method = RequestMethod.POST, apiTitle = "审核——工艺路线")
    @ApiOperation("审核——工艺路线")
    @Transactional(rollbackFor = Exception.class)
    public R auditOfCraft( @ApiParam(value = "工艺路线id", required = true) @RequestParam(value = "craftId") Long craftId,
                           @ApiParam(value = "审核人id") @RequestParam(value = "auditManIds",required = false) Long auditManIds){

        return craftService.auditAndUnOfCraft(craftId, auditManIds, 0);
    }

    @EvApiByToken(value = "/apis/mes/craft/reverseAuditCraft", method = RequestMethod.POST, apiTitle = "反审核——工艺路线")
    @ApiOperation("反审核——工艺路线")
    @Transactional(rollbackFor = Exception.class)
    public R reverseAuditOfCraft( @ApiParam(value = "工艺路线id", required = true) @RequestParam(value = "craftId") Long craftId){
        Long auditManIds=0L;
        return craftService.auditAndUnOfCraft(craftId, auditManIds, 1);
    }

    @EvApiByToken(value = "/apis/mes/craft/listOfHeadCraft", method = RequestMethod.POST, apiTitle = "工艺路线列表")
    @ApiOperation("获取工艺路线列表--主表")
    @Transactional(rollbackFor = Exception.class)
    public R craftOfHeadList(@ApiParam(value = "当前第几页", required = true) @RequestParam(value = "pageno", defaultValue = "1") int pageno,
                         @ApiParam(value = "一页多少条", required = true) @RequestParam(value = "pagesize", defaultValue = "20") int pagesize,
                             @ApiParam(value = "状态") @RequestParam(value = "useStatus", required = false) Integer useStatus,
                             @ApiParam(value = "审核状态") @RequestParam(value = "auditSign", defaultValue = "", required = false) Integer auditSign,
                             @ApiParam(value = "工艺名称") @RequestParam(value = "name", defaultValue = "", required = false) String name) {
        Map<String, Object> params = Maps.newHashMapWithExpectedSize(5);
        params.put("name", name);
        params.put("offset", (pageno - 1) * pagesize);
        params.put("limit", pagesize);
        params.put("useStatus", useStatus);
        params.put("auditSign", auditSign);
        List<Map<String, Object>> list = craftService.listForMap(params);
        int count = craftService.countListForMap(params);

        Map<String, Object> results = Maps.newHashMapWithExpectedSize(1);

        if (list.size() > 0) {
            DsResultResponse dsRet = new DsResultResponse();
            dsRet.setDatas(list);
            dsRet.setPageno(pageno);
            dsRet.setPagesize(pagesize);
            dsRet.setTotalRows(count);
            dsRet.setTotalPages( (count + pagesize - 1) / pagesize);
            results.put("data", dsRet);
        }
        return R.ok(results);
    }

    @EvApiByToken(value = "/apis/mes/craft/listOfBadyCraft", method = RequestMethod.POST, apiTitle = "工艺路线列表")
    @ApiOperation("获取工艺路线列表--子表")
    @Transactional(rollbackFor = Exception.class)
    public R craftOfBodyList(@ApiParam(value = "当前第几页", required = true) @RequestParam(value = "pageno", defaultValue = "1") int pageno,
                         @ApiParam(value = "一页多少条", required = true) @RequestParam(value = "pagesize", defaultValue = "20") int pagesize,
                         @ApiParam(value = "工艺路线主键", required = true) @RequestParam(value = "craftId") Long craftId) {
        Map<String, Object> params = Maps.newHashMapWithExpectedSize(5);
        params.put("id", craftId);
        params.put("offset", (pageno - 1) * pagesize);
        params.put("limit", pagesize);

        List<Map<String, Object>> list = craftService.listBodyForMap(params);
        int count = craftService.countListBodyForMap(params);
        Map<String, Object> results = Maps.newHashMapWithExpectedSize(1);
        if (list.size() > 0) {

            List<Map<String, Object>> itemDetals= list.stream().sorted((v1,v2)->Integer.parseInt(v1.get("serialNumber").toString())>Integer.parseInt(v2.get("serialNumber").toString())?1:-1).collect(Collectors.toList());

            DsResultResponse dsRet = new DsResultResponse();
            dsRet.setDatas(itemDetals);
            dsRet.setPagesize(pagesize);
            dsRet.setPageno(pageno);
            dsRet.setTotalRows(count);
            dsRet.setTotalPages( (count + pagesize - 1) / pagesize);
            results.put("data", dsRet);
        }
        return R.ok(results);
    }


    @EvApiByToken(value = "/apis/mes/craft/craftOfDetail", method = RequestMethod.POST, apiTitle = "工艺路线详情")
    @ApiOperation("工艺路线详情")
    public R detailOfCraft( @ApiParam(value = "工艺路线id", required = true) @RequestParam(value = "craftId") Long craftId) {

        return craftService.getCraftOfDetail(craftId);
    }

    @EvApiByToken(value = "/apis/mes/craft/prcessDetalsOfCraft", method = RequestMethod.POST, apiTitle = "检验项目详情")
    @ApiOperation("检验项目详情")
    public R prcessDetalOfCraft( @ApiParam(value = "工艺明细行主键", required = true) @RequestParam(value = "itemId") Long itemId) {

        return craftService.getProcessOfDetail(itemId);
    }

    @EvApiByToken(value = "/apis/mes/craft/batchDeleteCraft", method = RequestMethod.POST, apiTitle = "删除工艺路线")
    @ApiOperation("删除工艺路线")
    @Transactional(rollbackFor = Exception.class)
    public R batchDeleteOfCraft( @ApiParam(value = "工艺路线id", required = true) @RequestParam(value = "craftId") Long[] craftId) {
        //  校验  ：工艺路线审核+工序计划是否引用
        return craftService.deletOfBatch(craftId);
    }


    /**
     *
     * @param file 工艺路线EXCEL 文件
     * Created by gumingjie on 2020-03-12.
     */
    @ResponseBody
    @EvApiByToken(value = "/apis/importExcel/craft", method = RequestMethod.POST, apiTitle = "工艺路线导入")
    @ApiOperation("工艺路线导入")
    @Transactional(rollbackFor = Exception.class)
    public R readCraftFile(@ApiParam(value = "文件信息", required = true) @RequestParam("file") MultipartFile file) {
        return craftService.importExcel(file);
    }

    /**
     *
     * Created by gumingjie on 2020-03-12.
     */
    @EvApiByToken(value = "/apis/mes/craft/batchAuditOfCraft", method = RequestMethod.POST, apiTitle = "批量审核——工艺路线")
    @ApiOperation("批量审核——工艺路线")
    @Transactional(rollbackFor = Exception.class)
    public R batchAuditOfCraft( @ApiParam(value = "工艺路线ids", required = true) @RequestParam(value = "ids") Long[] craftId){
        if (craftId.length > 0) {
            Long userId = ShiroUtils.getUserId();
            List<CraftDO> craftDOList = Lists.newArrayList();
            for (Long id : craftId) {
                CraftDO craftDO = craftService.get(id);
                if (craftDO == null) {
                    return R.error(messageSourceHandler.getMessage("common.massge.haveNoThing", null));
                }
                if (Objects.equals(craftDO.getAuditSign(), Constant.OK_AUDITED)) {
                    //已审核请勿重复操作！
                    return R.error(messageSourceHandler.getMessage("common.massge.okAudit", null));
                }
                craftDOList.add(craftDO);
            }

            for (CraftDO craftDO : craftDOList) {
                craftDO.setAuditSign(Constant.OK_AUDITED);
                craftDO.setAuditId(userId);
                craftService.update(craftDO);
            }

            return R.ok();
        }
        return R.error();

    }


}
